;主引导程序
;-----------------------------------------------
%include "boot.inc"
SECTION MBR vstart=0x7c00
    mov ax, cs
    mov ds, ax
    mov es, ax
    mov ss, ax
    mov fs, ax
    mov sp, 0x7c00
    mov ax, 0xb800      ;从起始地址 OxB8000 --OxBFFFF ，这片 32KB 大小的内存区域是用于文本显示。
    mov gs, ax
;清屏
;利用 Ox06 号功能，上卷全部行，则可清屏
;-----------------------------------------------------------
; INT Ox1O 功能号： Ox06 功能描述：上卷窗口
;------------------------------------------------------
;输入：
;AH 功能号＝ Ox06
;AL ＝上卷的行数（如果为 ，表示全部）
;BH ＝上卷行属性
;(CL, CH) ＝窗口左上角的（X,Y）位置
;(DL, DH) ＝窗口右下角的（X,Y）位置
;无返回值：

    mov ax, 0x600
    mov bx, 0x700
    mov cx, 0        ;左上角：（0,0）
    mov dx, 0x184f   ;右下角: (80,25)
                     ; VGA 文本模式中，一行只能容纳 80 个字符，共 25行
                     ;下标从0开始，所以 Ox18=24, 0x4f=79
    int 0x10         ;int 0x10

;;;;;;;;;向显存输出，实现打印字符串;;;;;;;;;;;;;;;;
    mov byte [gs:0x00], '1'
    mov byte [gs:0x01], 0xA4

    mov byte [gs:0x02], ' '
    mov byte [gs:0x03], 0xA4

    mov byte [gs:0x04], 'M'
    mov byte [gs:0x05], 0xA4

    mov byte [gs:0x06], 'B'
    mov byte [gs:0x07], 0xA4

    mov byte [gs:0x08], 'R'
    mov byte [gs:0x09], 0xA4
;;;;;;;;;;;;;;;打印字符串结束;;;;;;;;;;;;;;;;;;;;;;;;;

    mov eax, LOADER_START_SECTOR ;起始扇区lba地址
    mov bx, LOADER_BASE_ADDR     ;写入的内存地址
    mov cx, 4                    ;读取的扇区数
    call re_disk_m_16
    jmp LOADER_BASE_ADDR + 0x300


;-----------------------------------------
;功能：读取硬盘n个扇区
;在16位模式下读取硬盘
;使用时查询表3-17
;-----------------------------------------
re_disk_m_16:
    mov esi,    eax    ;备份 eax
    mov di,     cx     ;备份 ex
;读写硬盘：
;第1步：设置要读取的扇区数
    mov dx, 0x1f2       ;Sector count
    mov al, cl
    out dx, al          ;读取的扇区数

    mov eax, esi        ;恢复 eax

;第2步：将LBA地址存入0x1f3 ~ 0x1f6
    ;LBA地址7～0位写入端口0x1f3
    mov dx, 0x1f3
    out dx, al
    ;LBA地址15～8位写入端口0x1f4
    mov cl, 8
    shr eax, cl
    mov dx, 0x1f4
    out dx, al
    ;LBA地址23～16位写入端口0x1f5
    shr eax, cl
    mov dx,0x1f5
    out dx, al

    shr eax,cl
    and al, 0x0f       ;lba地址24～27位写入端口0x1f6
    or al, 0xe0        ;设置7～4位为1110，表示lba模式
    mov dx, 0x1f6
    out dx, al
;第3步：向0x1f7端口写入读命令，0x20
    mov dx,0x1f7
    mov al,0x20
    out dx,al

;第4步:等待硬盘准备好
    .not_ready:
        ;同一端口，写时表示写入命令字，读时表示读入硬盘状态
        nop
        in al,dx
        and al,0x88    ;第4位为1表示硬盘控制器已经准备好数据传输;第7位为1表示硬盘忙
        cmp al,0x08
        jnz .not_ready
;第5步：从0x1f0端口读取数据
        mov ax, di
        mov dx, 256
        mul dx
        mov cx ,ax   ;di为要读取的扇区数，一个扇区有512字节，每次读取一个字;共需di*512/2次,所以di*256
        mov dx, 0x1f0
    .go_on_read:
        in ax, dx
        mov [bx],ax
        add bx,2
        loop .go_on_read
        ret

    times 510-($-$$) db 0
    db 0x55,0xaa

